package com.example.cloud.service.business.medical.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.example.cloud.constants.CommonConstants;
import com.example.cloud.constants.StateConstants;
import com.example.cloud.dao.business.medical.ExecuteRecordRepository;
import com.example.cloud.dao.business.medical.TreatPlanCourseProductRepository;
import com.example.cloud.dao.business.medical.TreatPlanHomeProductRepository;
import com.example.cloud.dao.business.medical.TreatPlanProductRepository;
import com.example.cloud.dao.finance.ChargeDetailsRepository;
import com.example.cloud.dao.mongdb.basic.info.MongoProductRepository;
import com.example.cloud.model.basic.Product;
import com.example.cloud.model.business.medical.ExecuteRecord;
import com.example.cloud.model.business.medical.TreatPlanCourseProduct;
import com.example.cloud.model.business.medical.TreatPlanHomeProduct;
import com.example.cloud.model.business.medical.TreatPlanProduct;
import com.example.cloud.model.dto.Result;
import com.example.cloud.model.finance.ChargeDetails;
import com.example.cloud.model.member.Member;
import com.example.cloud.model.system.User;
import com.example.cloud.service.basic.info.MemberService;
import com.example.cloud.service.business.medical.ExecuteService;
import com.example.cloud.service.business.medical.TreatPlanProductService;
import com.example.cloud.utils.BusinessUtil;
import com.example.cloud.utils.RequestUtil;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import static java.util.stream.Collectors.toList;

/**
 * Created by wangtao on 2018/6/6.
 */
@Service
public class TreatPlanProductServiceImpl implements TreatPlanProductService {

    private static final Logger logger = Logger.getLogger(TreatPlanProductServiceImpl.class);

    @PersistenceContext
    EntityManager em;

    @Autowired
    private ExecuteService executeService;

    @Autowired
    private ExecuteRecordRepository executeRecordRepository;

    @Autowired
    private TreatPlanProductRepository treatPlanProductRepository;

    @Autowired
    private TreatPlanCourseProductRepository treatPlanCourseProductRepository;

    @Autowired
    private TreatPlanHomeProductRepository treatPlanHomeProductRepository;

    @Autowired
    private MongoProductRepository mongoProductRepository;

    @Autowired
    private MemberService memberService;

    @Autowired
    private ChargeDetailsRepository chargeDetailsRepository;

    @Override
    public TreatPlanProduct findOne(Long id) {
        return treatPlanProductRepository.findOne(id);
    }

    @Override
    public List<TreatPlanProduct> findByProjectId(Long projectId) {
        return treatPlanProductRepository.findByProjectIdAndDeleteFlag(projectId,0).stream().filter(product -> product.getQuantity() > product.getExecute()).collect(toList());
    }

    @Override
    @Transactional
    public TreatPlanProduct doSave(TreatPlanProduct record) {
        BusinessUtil.appendRecord(record);
        return treatPlanProductRepository.save(record);
    }

    @Override
    @Transactional
    public void batchInsert(List<TreatPlanProduct> records, Long patientId) {
        for (TreatPlanProduct record : records) {
            record.setId(null);
            record.setPatientId(patientId);
            // 设置会员信息
            ChargeDetails details = new ChargeDetails();
            Member member = memberService.findByPatientId(patientId);
            if (member != null) {
                record.setMemberId(member.getId());
                details.setMemberId(member.getId());
            }
            record.setTotalPrice(record.getPrice().multiply(new BigDecimal(record.getQuantity())));
            record.setCreationTime(null);
            BusinessUtil.appendRecord(record);
            record = treatPlanProductRepository.save(record);

            // 生成收费
            generateChargeDetails(record, patientId, details);
        }
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public void generateChargeDetails(TreatPlanProduct record, Long patientId, ChargeDetails details) {
        details.setPatientId(patientId);
        details.setBusinessId(record.getId());
        details.setBusinessType(StateConstants.CHARGE_BUSINESS_TYPE_ONE);
        details.setChargeType(StateConstants.CHARGE_CHARGE_TYPE_PRODUCT);
        details.setItemId(record.getProductId());
        details.setItemName(record.getProductName());
        details.setQuantity(record.getQuantity());
        details.setPrice(record.getPrice());
        details.setTotalPrice(record.getTotalPrice());
        BusinessUtil.appendRecord(details);
        chargeDetailsRepository.save(details);
    }

    @Override
    @Transactional
    public Result doDeleteById(Long id) {
        Result result = new Result();
        result.setCode(CommonConstants.SUCCESS);
        result.setMsg("删除成功");
        // 校验删除条件
        boolean check = checkDelete(id);
        if (!check) {
            result.setCode(CommonConstants.FAILURE);
            result.setMsg("购买成功后不能删除");
            return result;
        }
        // 逻辑删除
        treatPlanProductRepository.delete(id);
        // 删除待收费
        chargeDetailsRepository.deleteByBusinessIdAndChargeType(id, StateConstants.CHARGE_CHARGE_TYPE_PRODUCT);
        return result;
    }

    public boolean checkDelete(Long id) {
        boolean check = true;
        TreatPlanProduct record = treatPlanProductRepository.findOne(id);
        // 已付款不能删除
        if (record.getChargeStatus() == StateConstants.CHARGE_STATUS_YES) {
            check = false;
        }
        return check;
    }

    @Override
    @Transactional
    public void doDelete(List<Long> ids) {
        // 逻辑删除
        StringBuilder sql = new StringBuilder("update treat_plan_product set delete_flag = 1 where id in(:ids)");
        Query query = em.createNativeQuery(sql.toString());
        query.setParameter("ids", ids);
        query.executeUpdate();
    }

    @Override
    @Transactional
    public void doExecute(TreatPlanProduct record, int status, String content) {
        User user = RequestUtil.getLoginUser();
        ExecuteRecord executeRecord = new ExecuteRecord();
        executeRecord.setPatientId(record.getPatientId());
        executeRecord.setComplaintId(record.getComplaintId());
        executeRecord.setOrderId(record.getId());
        executeRecord.setStatus(status);
        executeRecord.setTreatType(StateConstants.EXECUTE_TREAT_TYPE_ONE);
        executeRecord.setItemType(StateConstants.EXECUTE_ITEM_TYPE_PRODUCT);
        executeRecord.setItemId(record.getProductId());
        executeRecord.setItemName(record.getProductName());
        executeRecord.setDoctorName(record.getCreatedBy());
        executeRecord.setDoctorRemark(record.getMedicalAdvice());
        executeRecord.setSource(record.getProductName());
        executeRecord.setTotalCount(record.getQuantity());
        executeRecord.setLaveCount(record.getQuantity() - record.getExecute());
        executeRecord.setMedicalTime(record.getCreationTime());
        executeRecord.setExecuteContent(content);
        executeRecord.setCreationTime(null);
        BusinessUtil.appendRecord(executeRecord);
        executeService.doSave(executeRecord);
        // 更新已执行次数
        if (status == StateConstants.EXECUTE_STATUS_YES) {
            BusinessUtil.appendRecord(record);
            treatPlanProductRepository.save(record);
        }
    }

    @Override
    public JSONArray doFindDisposal(Long complaintId) {
        // 再查询医学护肤品(非药品即医学护肤品)
        JSONArray resultList = new JSONArray();
        // 先查询添加的所有医药产品
        List<Long> ids = new ArrayList<>();
        List<TreatPlanProduct> list1 = treatPlanProductRepository.findByComplaintIdAndDeleteFlag(complaintId, 0);
        for (TreatPlanProduct planProduct : list1) {
//            if (planProduct.getExecute() < planProduct.getQuantity()) {
                Product product = mongoProductRepository.findOne(planProduct.getProductId());
                if (product != null && product.getIsDrug() == StateConstants.PRODUCT_IS_DRUG_NO) {
                    JSONObject json = new JSONObject();
                    json.put("itemName", product.getName());
                    json.put("useMethod", planProduct.getMedicalAdvice());
                    json.put("creationTime", planProduct.getCreationTime());
                    resultList.add(json);
                }
//            }
        }
        List<TreatPlanCourseProduct> list2 = treatPlanCourseProductRepository.findByComplaintIdAndDeleteFlag(complaintId, 0);
        for (TreatPlanCourseProduct courseProduct : list2) {
//            if (courseProduct.getExecute() < courseProduct.getQuantity()) {
                Product product = mongoProductRepository.findOne(courseProduct.getProductId());
                if (product != null && product.getIsDrug() == StateConstants.PRODUCT_IS_DRUG_NO) {
                    JSONObject json = new JSONObject();
                    json.put("itemName", product.getName());
                    json.put("useMethod", courseProduct.getMedicalAdvice());
                    json.put("creationTime", courseProduct.getCreationTime());
                    resultList.add(json);
                }
//            }
        }
        List<TreatPlanHomeProduct> list3 = treatPlanHomeProductRepository.findByComplaintIdAndDeleteFlag(complaintId, 0);
        for (TreatPlanHomeProduct homeProduct : list3) {
//            if (homeProduct.getExecute() < homeProduct.getQuantity()) {
                Product product = mongoProductRepository.findOne(homeProduct.getProductId());
                if (product !=null && product.getIsDrug() == StateConstants.PRODUCT_IS_DRUG_NO) {
                    JSONObject json = new JSONObject();
                    json.put("itemName", product.getName());
                    json.put("useMethod", homeProduct.getMedicalAdvice());
                    json.put("creationTime", homeProduct.getCreationTime());
                    resultList.add(json);
                }
//            }
        }
        return resultList;
    }

    @Override
    public JSONArray doFindDrug(Long complaintId) {
        JSONArray resultList = new JSONArray();
        // 先查询添加的所有医药产品
        List<Long> ids = new ArrayList<>();
        List<TreatPlanProduct> list1 = treatPlanProductRepository.findByComplaintIdAndDeleteFlag(complaintId, 0);
        for (TreatPlanProduct planProduct : list1) {
//            if (planProduct.getExecute() < planProduct.getQuantity()) {
                Product product = mongoProductRepository.findOne(planProduct.getProductId());
                if(product != null && product.getIsDrug() == StateConstants.PRODUCT_IS_DRUG_YES && product.getToxic() == StateConstants.PRODUCT_TOXIC_NO
                        && product.getInject() == StateConstants.PRODUCT_INJECT_NO){
                    JSONObject json = (JSONObject)JSON.toJSON(product);
                    json.put("quantity", planProduct.getQuantity());
                    json.put("instructions", planProduct.getMedicalAdvice());
                    json.put("totalPrice", planProduct.getTotalPrice());
                    json.put("creationTime", planProduct.getCreationTime());
                    resultList.add(json);
                }
//            }
        }
        List<TreatPlanCourseProduct> list2 = treatPlanCourseProductRepository.findByComplaintIdAndDeleteFlag(complaintId, 0);
        for (TreatPlanCourseProduct courseProduct : list2) {
//            if (courseProduct.getExecute() < courseProduct.getQuantity()) {
                Product product = mongoProductRepository.findOne(courseProduct.getProductId());
                if(product != null && product.getIsDrug() == StateConstants.PRODUCT_IS_DRUG_YES && product.getToxic() == StateConstants.PRODUCT_TOXIC_NO
                        && product.getInject() == StateConstants.PRODUCT_INJECT_NO){
                    JSONObject json = (JSONObject)JSON.toJSON(product);
                    json.put("quantity", courseProduct.getQuantity());
                    json.put("instructions", courseProduct.getMedicalAdvice());
                    json.put("totalPrice", courseProduct.getTotalPrice());
                    json.put("creationTime", courseProduct.getCreationTime());
                    resultList.add(json);
                }
//            }
        }
        List<TreatPlanHomeProduct> list3 = treatPlanHomeProductRepository.findByComplaintIdAndDeleteFlag(complaintId, 0);
        for (TreatPlanHomeProduct homeProduct : list3) {
//            if (homeProduct.getExecute() < homeProduct.getQuantity()) {
                Product product = mongoProductRepository.findOne(homeProduct.getProductId());
                if(product != null && product.getIsDrug() == StateConstants.PRODUCT_IS_DRUG_YES && product.getToxic() == StateConstants.PRODUCT_TOXIC_NO
                        && product.getInject() == StateConstants.PRODUCT_INJECT_NO){
                    JSONObject json = (JSONObject)JSON.toJSON(product);
                    json.put("quantity", homeProduct.getQuantity());
                    json.put("instructions", homeProduct.getMedicalAdvice());
                    json.put("totalPrice", homeProduct.getTotalPrice());
                    json.put("creationTime", homeProduct.getCreationTime());
                    resultList.add(json);
                }
//            }
        }
        return resultList;
    }

    @Override
    public JSONArray doFindInject(Long complaintId) {
        JSONArray resultList = new JSONArray();
        // 先查询添加的所有医药产品
        List<Long> ids = new ArrayList<>();
        List<TreatPlanProduct> list1 = treatPlanProductRepository.findByComplaintIdAndDeleteFlag(complaintId, 0);
        for (TreatPlanProduct planProduct : list1) {
//            if (planProduct.getExecute() < planProduct.getQuantity()) {
                Product product = mongoProductRepository.findOne(planProduct.getProductId());
                if (product != null && product.getInject() == StateConstants.PRODUCT_INJECT_YES) {
                    JSONObject json = (JSONObject)JSON.toJSON(product);
                    json.put("instructions", planProduct.getMedicalAdvice());
                    json.put("quantity", planProduct.getQuantity());
                    json.put("totalPrice", planProduct.getTotalPrice());
                    json.put("creationTime", planProduct.getCreationTime());
                    resultList.add(json);
                }
//            }
        }
        List<TreatPlanCourseProduct> list2 = treatPlanCourseProductRepository.findByComplaintIdAndDeleteFlag(complaintId, 0);
        for (TreatPlanCourseProduct courseProduct : list2) {
//            if (courseProduct.getExecute() < courseProduct.getQuantity()) {
                Product product = mongoProductRepository.findOne(courseProduct.getProductId());
                if (product != null && product.getInject() == StateConstants.PRODUCT_INJECT_YES) {
                    JSONObject json = (JSONObject)JSON.toJSON(product);
                    json.put("instructions", courseProduct.getMedicalAdvice());
                    json.put("quantity", courseProduct.getQuantity());
                    json.put("totalPrice", courseProduct.getTotalPrice());
                    json.put("creationTime", courseProduct.getCreationTime());
                    resultList.add(json);
                }
//            }
        }
        List<TreatPlanHomeProduct> list3 = treatPlanHomeProductRepository.findByComplaintIdAndDeleteFlag(complaintId, 0);
        for (TreatPlanHomeProduct homeProduct : list3) {
//            if (homeProduct.getExecute() < homeProduct.getQuantity()) {
                Product product = mongoProductRepository.findOne(homeProduct.getProductId());
                if (product != null && product.getInject() == StateConstants.PRODUCT_INJECT_YES) {
                    JSONObject json = (JSONObject)JSON.toJSON(product);
                    json.put("instructions", homeProduct.getMedicalAdvice());
                    json.put("quantity", homeProduct.getQuantity());
                    json.put("totalPrice", homeProduct.getTotalPrice());
                    json.put("creationTime", homeProduct.getCreationTime());
                    resultList.add(json);
                }
//            }
        }
        return resultList;
    }

    @Override
    public JSONArray doFindToxic(Long complaintId) {
        JSONArray resultList = new JSONArray();
        // 先查询添加的所有医药产品
        List<TreatPlanProduct> list1 = treatPlanProductRepository.findByComplaintIdAndDeleteFlag(complaintId, 0);
        for (TreatPlanProduct planProduct : list1) {
//            if (planProduct.getExecute() < planProduct.getQuantity()) {
                Product product = mongoProductRepository.findOne(planProduct.getProductId());
                if (product != null && product.getToxic() == StateConstants.PRODUCT_TOXIC_YES) {
                    JSONObject json = (JSONObject)JSON.toJSON(product);
                    json.put("quantity", planProduct.getQuantity());
                    json.put("totalPrice", planProduct.getTotalPrice());
                    json.put("instructions", planProduct.getMedicalAdvice());
                    json.put("creationTime", planProduct.getCreationTime());
                    resultList.add(json);
                }
//            }
        }
        List<TreatPlanCourseProduct> list2 = treatPlanCourseProductRepository.findByComplaintIdAndDeleteFlag(complaintId, 0);
        for (TreatPlanCourseProduct courseProduct : list2) {
//            if (courseProduct.getExecute() < courseProduct.getQuantity()) {
                Product product = mongoProductRepository.findOne(courseProduct.getProductId());
                if (product != null && product.getToxic() == StateConstants.PRODUCT_TOXIC_YES) {
                    JSONObject json = (JSONObject)JSON.toJSON(product);
                    json.put("quantity", courseProduct.getQuantity());
                    json.put("totalPrice", courseProduct.getTotalPrice());
                    json.put("instructions", courseProduct.getMedicalAdvice());
                    json.put("creationTime", courseProduct.getCreationTime());
                    resultList.add(json);
                }
//            }
        }
        List<TreatPlanHomeProduct> list3 = treatPlanHomeProductRepository.findByComplaintIdAndDeleteFlag(complaintId, 0);
        for (TreatPlanHomeProduct homeProduct : list3) {
//            if (homeProduct.getExecute() < homeProduct.getQuantity()) {
                Product product = mongoProductRepository.findOne(homeProduct.getProductId());
                if (product != null && product.getToxic() == StateConstants.PRODUCT_TOXIC_YES) {
                    JSONObject json = (JSONObject)JSON.toJSON(product);
                    json.put("quantity", homeProduct.getQuantity());
                    json.put("totalPrice", homeProduct.getTotalPrice());
                    json.put("instructions", homeProduct.getMedicalAdvice());
                    json.put("creationTime", homeProduct.getCreationTime());
                    resultList.add(json);
                }
//            }
        }
        return resultList;
    }
}
